package cac.common;/*
 *@program:wms-sortSys
 *@description:封装创建命令日志方法
 *@author: lsl
 *@Time: 2023/1/15  12:05
 */


import cac.fenjian.resource.AoTask.MsTaskPackage.dao.MsTaskPackageDao;
import cac.fenjian.resource.materialreceipt.dao.PackageUnpackDao;
import cac.fenjian.resource.mssslshelves.dao.MsGkLogDao;
import cac.fenjian.resource.mssslshelves.rest.MsSslShelvesRest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

@Service
@Slf4j
public class CreateCommonLog {

    @Autowired
    private MsGkLogDao msGkLogDao;

    @Autowired
    private Environment environment;

    @Autowired
    private MsSslShelvesRest msSslShelvesRest;

    @Autowired
    private MsTaskPackageDao msTaskPackageDao;
    @Autowired
    private PackageUnpackDao packageUnpackDao;

    @Value("${pathProperty.isTest}")
    private boolean isTest;

    /***
     * yebo 添加，兼容测试环境
     * 测试环境生成上位id规则：99990开头
     * */
    public Long createWmsTaskId() {
        if (isTest) { //是否测试环境
            Integer uuid = UUID.randomUUID().toString().hashCode();
            uuid = uuid < 0 ? -uuid : uuid;
            String suid = "99990" + uuid;
            Long wmsTaskId = Long.valueOf(suid);
            log.info("生成测试环境上位id》》》》》》》》》》》》》》》" + wmsTaskId);
            return wmsTaskId;
        } else {//正式环境
            Integer uuid = UUID.randomUUID().toString().hashCode();
            uuid = uuid < 0 ? -uuid : uuid;
            Long wmsTaskId = Long.valueOf(uuid);
            return wmsTaskId;
        }
    }

    /**
     * /出库操作日志创建
     *
     * @param map
     * @return
     */
    public HashMap outBound(HashMap map) {
        String result;
        HashMap hashMap = new HashMap();
       /* Integer uuid = UUID.randomUUID().toString().hashCode();
        uuid = uuid < 0 ? -uuid : uuid;
        Long wmsTaskId = Long.valueOf(uuid);*/
        Long wmsTaskId = createWmsTaskId();//yebo 2023-04-20 更改，根据配置文件生成测试环境任务id或正式环境任务id
        try {
            map.put("isBack", "N");
            map.put("wmsTaskId", wmsTaskId);
            //判断操作的箱子编码是否存在未完成任务
            int isUnsuccess = msGkLogDao.selectUnSuccessTask(map);
            if (isUnsuccess == 0) {
                //创建日志
                msGkLogDao.creatLog(map, map.toString());
                hashMap.put("retCode", "200");
                hashMap.put("retMsg", "创建日志成功！");
            } else {
                hashMap.put("retCode", "201");
                hashMap.put("retMsg", map.get("palletCode").toString() + "该缓存箱存在未完成任务");
            }
        } catch (Exception e) {
            e.printStackTrace();
            hashMap.put("retCode", "201");
            hashMap.put("retMsg", "创建出库操作日志失败！");
        }
        return hashMap;
    }


    /**
     * 入库日志创建
     *
     * @param map
     * @return
     */
    @Transactional
    public String inBound(HashMap map) {
        String result;
       /* Integer uuid = UUID.randomUUID().toString().hashCode();
        uuid = uuid < 0 ? -uuid : uuid;
        Long wmsTaskId = Long.valueOf(uuid);*/
        Long wmsTaskId = createWmsTaskId();//yebo 2023-04-20 更改，根据配置文件生成测试环境任务id或正式环境任务id
        try {
            map.put("wmsTaskId", wmsTaskId);
            int count = msGkLogDao.selectUnSuccessTask(map);
            if (count < 1) {
                //创建入库命令日志
                msGkLogDao.creatLog(map, map.toString());
                //修改该箱子编码旧出库日志
                msGkLogDao.updateOutBoundTask(map);
                result = "200";
            } else {
                 result = "存在未完成任务！";
            }
        } catch (Exception e) {
            e.printStackTrace();
            result = "操作失败";
        }
        return result;
    }


    /**
     * 流量控制
     * 需要参数：func-叫箱类型，palletCode-操作盘编号,endCode-结束位置,boxType-操作盘类型
     * @return
     */
    @Transactional
    public HashMap callWCSInterface(HashMap map) {
        HashMap result = new HashMap();
        boolean isExistsBackTask = false;
        long dateflag = System.currentTimeMillis();
        try {
            log.info("【开始调用流量控制--start】==========func=="+map.get("func")+"=========【时间戳："+dateflag+"】");
            if (map.get("func").equals("receive")) {
                //判断是否存在已完成的接收出库任务，并且创建了回库任务指令日志，执行回库操作。
                if (map.containsKey("palletCode")) {
                    String param = (String) map.get("endCode");
                    String endCode = param.substring(5);
                    map.put("backCode", endCode);
                    HashMap backTask = msGkLogDao.backTask(map);
                    map.put("preWmsTaskId", backTask.get("wmsTaskId"));
                    //当存在回库任务，调用wcs接口下发任务
                    if (backTask != null && !backTask.isEmpty()) {
                        msSslShelvesRest.doTask(backTask);
                        isExistsBackTask = true;
                    }
                }
                //接收
                //操作位流量控制参数
                Integer flowControlReceive = Integer.parseInt(environment.getProperty("flowControl.receive"));
                //获取已完成且未回库操作位缓存箱数量
                Integer isFinshCount = msGkLogDao.selecFinishtNum(map);
                //获取执行中操作位缓存箱数量
                Integer onWayCount = msGkLogDao.selectOnWayNum(map);
                //下发待调用wcs任务数量
                Integer taskStayCallCount = flowControlReceive - isFinshCount - onWayCount;
                log.info("当前操作位剩余可放数量:" + taskStayCallCount + "个");
                //待下发任务
                List<HashMap> stayCallWCSTasks = msGkLogDao.stayCallWCSTasks(map);
                if (!stayCallWCSTasks.isEmpty()) {
                    if (taskStayCallCount > 0 && stayCallWCSTasks != null && stayCallWCSTasks.size() > 0) {
                        //若可放位置数量小于可下发任务数量->taskCount ;else ->stayListSize
                        Integer count = taskStayCallCount < stayCallWCSTasks.size() ? taskStayCallCount : stayCallWCSTasks.size();
                        String tmpTaskId = "";
                        for (int i = 0; i < count; i++) {
                            //2023-06-13 lqc
                            //查询当前任务位置
                            String locationIsRigth = msGkLogDao.locationIsRigth(stayCallWCSTasks.get(0));
                            //如果货架位置和任务位置相同
                            if (stayCallWCSTasks.get(0).get("startCode").equals(locationIsRigth)) {
                                //向wcs下发指令
                                if (i == 0) {
                                    stayCallWCSTasks.get(i).put("preWmsTaskId", map.get("preWmsTaskId"));
                                } else {
                                    stayCallWCSTasks.get(i).put("preWmsTaskId", tmpTaskId);
                                }
                                tmpTaskId = (String) stayCallWCSTasks.get(i).get("wmsTaskId");
                                msSslShelvesRest.doTask(stayCallWCSTasks.get(i));
                                result.put("retCode", "200");
                                result.put("msg", "已下发排队任务中的托盘");
                            } else {
                                result.put("retCode", "201");
                                result.put("msg", "预下发的任务不在货位上，等待回库后下发！");
//                                //查询巷道，货位
//                                HashMap rsl=msGkLogDao.searchShelvesCode(stayCallWCSTasks.get(0));
//                                if(!Objects.isNull(rsl)){
//                                    msGkLogDao.updateTask(rsl,stayCallWCSTasks.get(0).get("wmsTaskId").toString());
//                                }
                                continue;
                            }
                        }
                    } else {
                        System.out.println("taskStayCallCount+++++++" + taskStayCallCount);
                        result.put("retCode", "200");
                        result.put("msg", "当前操作台无可放缓存箱位置！");
                    }
                } else {
                    result.put("retCode", "200");
                    result.put("msg", "任务已完成，无等待任务！");
                }
            } else if (map.get("func").equals("sort")) {
                log.info("【开始调用流量控制1】==========func=="+map.get("func")+"=========【时间戳："+dateflag+"】====map="+map.toString());
                //判断是否存在已完成的接收出库任务，并且创建了回库任务指令日志，执行回库操作。
                if (map.containsKey("palletCode")) {
                    String param = (String) map.get("endCode");
                    String endCode = param.substring(5);
                    map.put("backCode", endCode);
                    HashMap backTask = msGkLogDao.backTask(map);
                    if (backTask != null && !backTask.isEmpty()) {
                        msSslShelvesRest.doTask(backTask);
                        isExistsBackTask = true;
                    }
                }
                //是否有分拣位结束位置未过1066点位任务
//                int unSortPassTask = msGkLogDao.isSortPassTask(map);
//                //没有
//                if (unSortPassTask == 0) {
//                    log.info("【开始调用流量控制】==========func=="+map.get("func")+"=========【时间戳："+dateflag+"】====unSortPassTask="+unSortPassTask);
                    //操作位流量控制参数
                    Integer flowControlReceive = 0;
                    if (map.get("boxType").equals("WORKBIN")) {
                        flowControlReceive = Integer.parseInt(environment.getProperty("flowControl.workbinSorting")); //操作位流量控制参数
                    } else if (map.get("boxType").equals("TOOL")) {
                        flowControlReceive = Integer.parseInt(environment.getProperty("flowControl.toolSorting"));
                    }
                    //获取已完成操作位箱子数量
                    Integer isFinshCount = msGkLogDao.selecFinishtNum(map);
                    //获取执行中操作位箱子数量
                    Integer onWayCount = msGkLogDao.selectOnWayNum(map);
                    //下发待调用wcs任务数量
                    Integer taskStayCallCount = flowControlReceive - isFinshCount - onWayCount;
                    //可以下发任务
                    List<HashMap> stayCallWCSTasks = msGkLogDao.stayCallWCSTasksBySort(map);
                    log.info("【开始调用流量控制2】==========func=="+map.get("func")+"=========【时间戳："+dateflag+"】====stayCallWCSTasks.length="+stayCallWCSTasks.size());
                    if (!stayCallWCSTasks.isEmpty()) {
                        log.info("【开始调用流量控制3】==========func=="+map.get("func")+"=========【时间戳："+dateflag+"】====taskStayCallCount="+taskStayCallCount);
                        if (taskStayCallCount > 0) {
                            //yebo 2023-04-06 新增校验，如果存在回库任务，判断当前回库的箱子是不是下一个指令要叫的箱
                            if (isExistsBackTask && stayCallWCSTasks.get(0).get("palletCode").equals(map.get("palletCode"))) {
                                log.info("执行任务的操作盘正在回库的路上,参数：" + map.toString());
                                result.put("retCode", "200");
                                result.put("msg", "执行的任务的操作盘正在回库的路上！");
                                return result;
                            }
                            //判断下发的盘子的库内起始位置是否等于任务起始位置
                            String locationIsRigth = msGkLogDao.locationIsRigth(stayCallWCSTasks.get(0));
                            log.info("【开始调用流量控制4】==========func=="+map.get("func")+"=========【时间戳："+dateflag+"】====locationIsRigth="+locationIsRigth+",startCode="+stayCallWCSTasks.get(0).get("startCode"));
                            //下发任务的工作包盘，对应起始位置是否与货架相同
                            if (stayCallWCSTasks.get(0).get("startCode").equals(locationIsRigth)) {
                                //位置相同。
                                msSslShelvesRest.doTask(stayCallWCSTasks.get(0));
                                //是否存在首次下发命令标识符，存在即返回首次下发命令的第一个任务的工作包id，第一个ao
                                if (map.containsKey("firstCall")) {
                                    //首次任务开始时，获取第一个分拣的工作包任务package_code，从而获取对应所有AO
                                    result.put("packageId", stayCallWCSTasks.get(0).get("packageId"));
                                    //首次任务开始时，获取第一个分拣的ao任务
                                    result.put("firstAo", stayCallWCSTasks.get(0).get("aoCode"));
                                }
                            } else {
                                //货位不同，不下发新任务，等待货物回到货架后下发。
                                result.put("msg", "预下发的任务不在货位上，等待回库后下发！");
                            }
                        }
                        result.put("msg", "已下发排队任务中的托盘！");
                    } else {
                        result.put("msg", "任务已完成，没有等待中的任务");
                    }
                    result.put("retCode", "200");
//                } else {
//                    result.put("retCode", "200");
//                    result.put("msg", "分拣任务正在进行中，请等待当前已下发任务全部执行完毕！");
//                }
                //判断操作为工作包回库操作
                if (map.containsKey("backTask") && map.get("backTask").equals("backTool")) {
                    //如果操作类型为，工作包回库操作，查询出下一个优先级的工作包任务
                    HashMap nextPackage = msGkLogDao.nextPackage(map);
                    if (nextPackage != null && !nextPackage.isEmpty()) {
                        //将工作包任务返回给前端，方便前端数据转换
                        result.put("nextPackage", nextPackage);
                        //对应工作包下的所有ao返回给前端。
                        result.put("aoCodes", msTaskPackageDao.searchAllAoByPackage(nextPackage));
                    }
                } else if (map.containsKey("backTask") && map.get("backTask").equals("backWorkBin")) {
                    //如果操作类型为缓存箱回库
                    //如果操作类型为，缓存箱回库操作，查询出下一个优先级的缓存箱任务
                    HashMap nextAo = msGkLogDao.nextPackage(map);
                    if (nextAo != null && !nextAo.isEmpty()) {
                        //获取下一个操作的缓存箱，对应AO
                        result.put("nextAo", nextAo.get("aoCode"));
                    }
                }
            } else if (map.get("func").equals("agv")) {
                //根据配送位置，查询先出的工作包对应的工作包盘
                List<HashMap> priorTool = msGkLogDao.searchPriorTool();
                //是否存在工作包任务。存在进行叫箱操作，不存在返回任务完成
                if (priorTool != null && !priorTool.isEmpty()) {
                    //遍历工作包任务集合,全部调用wcs下发，启动出库
                    for (int i = 0; i < priorTool.size(); i++) {
                        msSslShelvesRest.doTask(priorTool.get(i));
                    }
                    result.put("retCode", "200");
                    result.put("msg", "配送任务启动成功！");
                } else {
                    result.put("retCode", "200");
                    result.put("msg", "配送任务已完成！");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            result.put("retCode", "201");
        } finally {
            return result;
        }

    }

    /**
     * yebo 2023-07-26
     * 拆包创建任务用
     * **/
    public HashMap unpackOutbindTask(String palletCode,String ip, String msTaskPackageId){
        Long wmsTaskId = createWmsTaskId();
        String palletType = "";
        if(palletCode.startsWith("1")){
            palletType = "WORKBIN";
        }else{
            palletType = "TOOL";
        }
        //1:查询该箱子/托盘是否存在任务并且是否再货架上

        HashMap palletMap = packageUnpackDao.queryPalletTask(palletCode);
        if(!Objects.isNull(palletMap)&&!palletMap.isEmpty()){
            //2:创建任务
            palletMap.put("ip",ip);
            palletMap.put("msTaskPackageId",msTaskPackageId);
            palletMap.put("wmsTaskId",wmsTaskId);
            palletMap.put("palletType",palletType);
            packageUnpackDao.insertGkLog(palletMap);
        }else{
            //2:创建任务到
        }
        //调用流量控制 func-叫箱类型，palletCode-操作盘编号,endCode-结束位置,boxType-操作盘类型
        HashMap map = new HashMap();
        map.put("func","sort");
        map.put("palletCode",palletCode);
        map.put("boxType",palletType);
        map.put("endCode",packageUnpackDao.queryConsole(ip,palletType));
        this.callWCSInterface(map);
        return null;
    }
}
